from django.shortcuts import render
from django.http import JsonResponse, HttpResponse
from django.views.decorators.http import require_http_methods
from django.conf import settings
from django.db.models import Sum
from main.models import *
import datetime
import calendar
import time
import pandas as pd

# Create your views here.


@require_http_methods(["POST"])
def qc_code(request):
    """ 二维码核验 """
    # 返回text格式的code=0000
    # print('post请求')
    # return HttpResponse('code=0000', content_type='text/plain')

    body = request.body.decode('utf-8')
    user_id = body.split('&&')[0].split('=')[1]

    ## 判断是否有订餐
    today = datetime.datetime.now().date()
    user_obj = UserDdingDineModel.objects.filter(userid=user_id, ddine_time=today).first()
    if user_obj:    # 已定餐
        if user_obj.code_time:
            # 判断user_obj.code_time记录的时间是否在60分钟以内, 如果是, 则返回code=0001，不是则返回code=0002
            now = datetime.datetime.now()
            if now - user_obj.code_time < datetime.timedelta(minutes=60):
                return HttpResponse('code=0000', content_type='text/plain')
            else:
                return HttpResponse('code=0009', content_type='text/plain')

        else:   # 初次核验
            user_obj.is_check = True
            user_obj.code_time = datetime.datetime.now()
            user_obj.save()
            return HttpResponse('code=0000', content_type='text/plain')

    else:   # 未订餐
        # 记录违规扫码的用户
        users = UserDdingDineModel.objects.filter(userid=user_id).first()
        if users:
            ScanningCodes.objects.create(userid=user_id, name=users.name, mobile=users.mobile)
        else:
            users = UserInfoModel.objects.filter(userid=user_id).first()
            ScanningCodes.objects.create(userid=user_id, name=users.name, mobile='')
        return HttpResponse('code=0009', content_type='text/plain')


def export_ddine_detail(request):
    """ 生成数据 """
    params = set_params_dict(request.GET.items())
    if params['date_range'] == 'null' or params['date_range'] == '':
        params['date_range'] = '1971-01-01,2099-01-07'
    start_time = params['date_range'].split(',')[0]
    start_end = params['date_range'].split(',')[1]
    data = UserDdingDineModel.objects.filter(ddine_time__range=(start_time, start_end), name__contains=params['username']).values()
    file_name = fr'{start_time}_{start_end}_{str(int(time.time() * 1000))}.xlsx'
    pd_data = pd.DataFrame(data)
    pd_data = pd_data[['name', 'mobile', 'ddine_time', 'num', 'amount']]
    pd_data['amount'] = pd_data['amount'].astype('float')
    pd_data.rename(columns={'name': '姓名', 'mobile': '手机号', 'ddine_time': '日期', 'num': '份数', 'amount': '金额'}, inplace=True)
    grouped_df = pd_data.groupby(['姓名', '手机号'], as_index=False).agg({'份数': 'sum', '金额': 'sum'})
    grouped_df.to_excel(f'{settings.MEDIA_ROOT}/{file_name}', index=False)
    return JsonResponse({'down': f'{settings.MEDIA_URL}{file_name}', 'file_name': file_name})


def export_ddine_no_detail(request):
    """ 不合并生成数据 """
    params = set_params_dict(request.GET.items())
    if params['date_range'] == 'null' or params['date_range'] == '':
        params['date_range'] = '1971-01-01,2099-01-07'
    start_time = params['date_range'].split(',')[0]
    start_end = params['date_range'].split(',')[1]
    data = UserDdingDineModel.objects.filter(ddine_time__range=(start_time, start_end), name__contains=params['username']).values()
    file_name = fr'{start_time}_{start_end}_{str(int(time.time() * 1000))}.xlsx'
    pd_data = pd.DataFrame(data)
    pd_data = pd_data[['name', 'mobile', 'ddine_time', 'num', 'amount']]
    pd_data['amount'] = pd_data['amount'].astype('float')
    pd_data.rename(columns={'name': '姓名', 'mobile': '手机号', 'ddine_time': '日期', 'num': '份数', 'amount': '金额'}, inplace=True)
    pd_data.to_excel(f'{settings.MEDIA_ROOT}/{file_name}', index=False)
    return JsonResponse({'down': f'{settings.MEDIA_URL}{file_name}', 'file_name': file_name})


def get_ddine_detail(request):
    """ 查询数据 """

    params = set_params_dict(request.GET.items())
    if params['date_range'] == 'null' or params['date_range'] == '':
        params['date_range'] = '2021-01-01,2099-01-07'
    start_time = params['date_range'].split(',')[0]
    start_end = params['date_range'].split(',')[1]
    obj = UserDdingDineModel.objects.filter(ddine_time__range=(start_time, start_end), name__contains=params['username']).order_by('-ddine_time')
    data = obj.values()
    total = obj.aggregate(num=Sum('num'), amount=Sum('amount'))
    return JsonResponse({'data': list(data), 'total': total})


def export_statistics_data(request):
    """ 导出数据HTML """
    return render(request, 'export_statistics_data.html')


def ddine_statistics(request):
    """ 统计份数 """

    """ 食堂师傅的全局设置 """
    ddine = DdingDineModel.objects.all().values().last()

    """ 判断订餐时间是否已截至 """
    res_cut_time = is_cut_time(ddine['cut_ddine_time'])
    if res_cut_time:    # 订餐时间已截至
        today_date = datetime.datetime.now().date() + datetime.timedelta(days=1)
    else:
        today_date = datetime.datetime.now().date()

    """ 获取未来7天用户订餐信息 """
    future_date = today_date + datetime.timedelta(days=7)
    data = generate_calendar(str(today_date), str(future_date))
    for day_i in range(len(data)):
        nums = UserDdingDineModel.objects.filter(ddine_time=data[day_i]['time']).values()
        data[day_i]['num'] = sum([n['num'] for n in nums])
        data[day_i]['amount'] = sum([float(n['amount']) for n in nums])
        data[day_i]['years'] = data[day_i]['time'].year
        data[day_i]['days'] = f"{data[day_i]['time'].month}-{data[day_i]['time'].day}"

    return JsonResponse({'data': data})


def ddine_get_setting(request):
    """ 获取全局设置数据 """
    ddine = DdingDineModel.objects.all().values().last()
    return JsonResponse(ddine)


def ddine_setting(request):
    """ 食堂师傅的全局设置 """
    params = set_params_dict(request.GET.items())
    ddine = DdingDineModel.objects.all().values().last()
    ddine['amount'] = params['amount']
    ddine['ddine_end_time'] = params['ddine_end_time']
    ddine['cut_ddine_time'] = params['cut_ddine_time']
    ddine['dine_type'] = params['dine_type']
    ddine['stop'] = True if params['stop'] == 'true' else False
    if ddine['stop']:
        ddine['stop_start_time'] = params['stop_start_time']
        ddine['stop_end_time'] = params['stop_end_time']
        UserDdingDineModel.objects.filter(ddine_time__range=(ddine['stop_start_time'], ddine['stop_end_time'])).update(num=0, amount=0, is_check=False)
    DdingDineModel.objects.update(**ddine)
    return JsonResponse({})


def ddine_meal(request):
    """ 定/退餐 """
    params = set_params_dict(request.GET.items())
    """ 食堂师傅的全局设置 """
    ddine = DdingDineModel.objects.all().values().last()
    UserDdingDineModel.objects.update_or_create(
        userid=params['userId'],
        name= params['name'],
        ddine_time__year=params['ddineDate'][:4],
        ddine_time__month=params['ddineDate'][5:7],
        ddine_time__day=params['ddineDate'][8:10],
        defaults = {
            'userid': params['userId'],
            'mobile': params['mobile'],
            'num': params['ddineNum'],
            'amount': float(params['ddineNum']) * float(ddine['amount']),
            'ddine_time': datetime.datetime.strptime(params['ddineDate'], "%Y-%m-%d").date(),
        }
    )
    return JsonResponse({})


def generate_calendar(start_date, end_date):
    """ 生成标签栏数据 """
    data = []
    start_date_obj = datetime.datetime.strptime(start_date, "%Y-%m-%d").date()
    end_date_obj = datetime.datetime.strptime(end_date, "%Y-%m-%d").date()
    current_date = start_date_obj
    while current_date < end_date_obj:
        data.append({'num': 0, 'amount': '0', 'time': current_date})
        current_date += datetime.timedelta(days=1)
    return data


def get_month_start_end_dates():
    """ 获取当月1号以及当月最后一天的日期 """
    today = datetime.datetime.now()
    first_day_of_month = today.replace(day=1)
    _, last_day_of_month = calendar.monthrange(today.year, today.month)
    last_day_of_month_date = first_day_of_month.replace(day=last_day_of_month)
    return first_day_of_month.date(), last_day_of_month_date.date()


def is_day_ddine(days_date, stop_time):
    """ 今日是否可以用餐 """
    given_date = datetime.datetime.strptime(days_date, "%Y-%m-%d").date()
    today_date = datetime.datetime.now().date()

    if given_date == today_date:
        return True
    return False


def is_cut_order_time(days_date, stop_time):
    """ 订餐截止时间说明 """
    bb_time = datetime.datetime.strptime(stop_time, "%H:%M").time()
    now_time = datetime.datetime.now().time()
    given_date = datetime.datetime.strptime(days_date, "%Y-%m-%d").date()
    today_date = datetime.datetime.now().date()

    if given_date == today_date:
        if now_time < bb_time: # 如果当前时间大于18:00
            return True    # 明日截至订餐时间，今日 18:00
        return False    # 啥都没有


def is_cut_order(days_date, stop_time):
    """ 判断订餐截止时间 """
    bb_time = datetime.datetime.strptime(stop_time, "%H:%M").time()
    now_time = datetime.datetime.now().time()
    given_date = datetime.datetime.strptime(days_date, "%Y-%m-%d").date()
    today_date = datetime.datetime.now().date()

    if given_date == today_date:
        return True
    else:
        today = datetime.datetime.now().date()
        difference = (given_date - today).days
        if difference == 1:
            if now_time > bb_time:  # 如果当前时间大于18:00
                return True
            else:
                return False
        else:
            return False


def is_leave(start_date, end_date, ddine_date):
    """ 判断师傅是否休假 """
    if start_date <= ddine_date <= end_date:
        return True
    return False


def get_week_date(navs_date):
    """ 获取本周日期 """
    weekday_index = navs_date.weekday()
    weekdays = ["周一", "周二", "周三", "周四", "周五", "周六", "周日"]
    weekday_str = weekdays[weekday_index]
    date_str = navs_date.strftime("%Y-%m-%d")
    return weekday_str, date_str


def is_cut_time(stop_ddine_time):
    """ 判断是否在订餐截止时间 """
    now = datetime.datetime.now()
    time_stop = now.replace(hour=int(stop_ddine_time[:2]), minute=int(stop_ddine_time[3:]), second=0, microsecond=0)
    # 判断当前时间是否大于18:00
    if now > time_stop:
        return True
    return False


def set_params_dict(query_dict):
    """ 提取GET请求数据为字典 """
    data = dict()
    for key, value in query_dict:
        data[key] = value
    return data


def get_or_create_user(request):
    """ 如果用户不存在则创建用户 """
    params = set_params_dict(request.GET.items())
    UserInfoModel.objects.get_or_create(**params)
    return JsonResponse({})


def get_user_dine_data(request):
    """ 获取用户订餐信息 """
    data = dict()
    params = set_params_dict(request.GET.items())

    """ 食堂师傅的全局设置 """
    ddine = DdingDineModel.objects.all().values().last()

    """ 判断订餐时间是否已截至 """
    res_cut_time = is_cut_time(ddine['cut_ddine_time'])
    if res_cut_time:    # 订餐时间已截至
        today_date = datetime.datetime.now().date() + datetime.timedelta(days=1)
    else:
        today_date = datetime.datetime.now().date()

    """ 获取未来7天用户订餐信息 """
    future_date = today_date + datetime.timedelta(days=7)
    data['navbars'] = generate_calendar(str(today_date), str(future_date))
    user_order = UserDdingDineModel.objects.filter(userid=params['userid'], ddine_time__range=(today_date, future_date)).values()

    for n in range(len(data['navbars'])):
        for u in range(len(user_order)):
            utime = user_order[u]['ddine_time'] # 用餐日期
            if utime == data['navbars'][n]['time']: # 标签页日期
                data['navbars'][n]['num'] = user_order[u]['num']
                data['navbars'][n]['amount'] = user_order[u]['amount']
                data['navbars'][n]['time'] = user_order[u]['ddine_time']

    for d in range(len(data['navbars'])):
        """ 判断师傅是否休假 """
        if ddine['stop']:
            res_leave = is_leave(ddine['stop_start_time'], ddine['stop_end_time'], data['navbars'][d]['time'])
        else:
            res_leave = False
        res_str = get_week_date(data['navbars'][d]['time'])
        data['navbars'][d]['name'] = res_str[0]	# 标签（师傅休假时这里变成：停餐。然后系统自动取消停餐日的所有单）
        data['navbars'][d]['is_stop_eating'] = res_leave # 是否不可以订餐：师傅休假时为true
        data['navbars'][d]['order_cancel'] = is_cut_order(res_str[1], ddine['cut_ddine_time']) # 是否不可以取消订餐：不允许取消当前订餐及超过18点后不允许需求明日订餐
        data['navbars'][d]['num'] = data['navbars'][d]['num']
        data['navbars'][d]['date'] = res_str[1]
        data['navbars'][d]['ddine_button_show'] = True if data['navbars'][d]['num'] > 0 else False
        data['navbars'][d]['order_cancel_note'] = is_cut_order_time(res_str[1], ddine['cut_ddine_time']) # 截至订餐时间说明
        data['navbars'][d]['day_ddine'] = is_day_ddine(res_str[1], ddine['cut_ddine_time']) # 今日是否可以用餐
        data['navbars'][d]['to_day'] = res_str[1][5:] # 今日是否可以用餐
        data['navbars'][d]['ddine_end_time'] = ddine['ddine_end_time'] # 结束取餐时间

    """ 用户统计订餐数 """
    data['dataLists'] = list()
    start_date, end_date = get_month_start_end_dates()

    m_user_order = UserDdingDineModel.objects.filter(userid=params['userid'], time__range=(start_date, end_date)).values()
    user_order = UserDdingDineModel.objects.filter(userid=params['userid']).values()
    def statis_num_amount(statis_list):
        number, amount = list(), list()
        for stat in statis_list:
            if int(stat['num']) > 0:
                number.append(int(stat['num']))
            amount.append(float(stat['amount']))
        return sum(number), sum(amount)
    m_order_number, m_order_amount = statis_num_amount(m_user_order)
    order_number, order_amount = statis_num_amount(user_order)

    data['dataLists'].append({'name': '月订餐数', 'number': m_order_number})
    data['dataLists'].append({'name': '月订餐额', 'number': m_order_amount})
    data['dataLists'].append({'name': '总订餐数', 'number': order_number})
    data['dataLists'].append({'name': '总订餐额', 'number': order_amount})
    return JsonResponse(data)
